home *** CD-ROM | disk | FTP | other *** search
/ Isometric Game Programming with DirectX 7.0 / Isometric Game Programming.iso / source / chapter18 / isohex18_1 / isohex18_1.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-08-30  |  12.3 KB  |  492 lines

  1. /*****************************************************************************
  2. IsoHex18_1.cpp
  3. Ernest S. Pazera
  4. 17AUG2000
  5. Start a WIN32 Application Workspace, add in this file
  6. Requires the following libs:
  7. ddraw.lib, dxguid.lib
  8. Requires the following files:
  9. DDFuncs.h.cpp, GDICanvas.h/cpp, IsoMouseMap.h/cpp,
  10. IsoScroller.h/cpp, IsoTilePlotter.h/cpp, IsoTileWalker.h/cpp
  11. TileSet.h/cpp. IsoHexCore.h, IsoHexDefs.h
  12. IsoRenderer.h/cpp
  13. *****************************************************************************/
  14.  
  15. //////////////////////////////////////////////////////////////////////////////
  16. //INCLUDES
  17. //////////////////////////////////////////////////////////////////////////////
  18. #define WIN32_LEAN_AND_MEAN  
  19.  
  20. #include <windows.h>  
  21. #include "DDFuncs.h"
  22. #include "TileSet.h"
  23. #include "IsoHexCore.h"
  24. #include "IsoRenderer.h"
  25.  
  26.  
  27. //////////////////////////////////////////////////////////////////////////////
  28. //DEFINES
  29. //////////////////////////////////////////////////////////////////////////////
  30. //name for our window class
  31. #define WINDOWCLASS "ISOHEX18"
  32. //title of the application
  33. #define WINDOWTITLE "IsoHex 18-1"
  34.  
  35. const int MAPWIDTH=200;
  36. const int MAPHEIGHT=400;
  37.  
  38. //////////////////////////////////////////////////////////////////////////////
  39. //PROTOTYPES
  40. //////////////////////////////////////////////////////////////////////////////
  41. bool Prog_Init();//game data initalizer
  42. void Prog_Loop();//main game loop
  43. void Prog_Done();//game clean up
  44.  
  45. //////////////////////////////////////////////////////////////////////////////
  46. //GLOBALS
  47. //////////////////////////////////////////////////////////////////////////////
  48. HINSTANCE hInstMain=NULL;//main application handle
  49. HWND hWndMain=NULL;//handle to our main window
  50.  
  51. //directdraw
  52. LPDIRECTDRAW7 lpdd=NULL;
  53. LPDIRECTDRAWSURFACE7 lpddsMain=NULL;
  54. LPDIRECTDRAWSURFACE7 lpddsBack=NULL;
  55. LPDIRECTDRAWSURFACE7 lpddsFrame=NULL;
  56.  
  57. //tilesets
  58. CTileSet tsBack;//background
  59. CTileSet tsTree;//tree foreground
  60. CTileSet tsUnit;//unit
  61.  
  62. //isohexcore components
  63. CTilePlotter TilePlotter;//plotter
  64. CTileWalker TileWalker;//walker
  65. CScroller Scroller;//scroller
  66. CMouseMap MouseMap;//mousemap
  67. CRenderer Renderer;//renderer
  68.  
  69. POINT ptScroll;//keep track of how quickly we scroll
  70.  
  71. //keep track of unit location
  72. POINT ptUnit;//current position of the unit
  73. POINT ptUnitOld;//last position of the unit
  74. ISODIRECTION idMoveUnit;//direction of movement
  75. bool bMoveUnit;//the unit should be moved
  76.  
  77. //map location structure
  78. struct MapLocation
  79. {
  80.     bool bTree;//false=no tree; true=tree
  81.     bool bUnit;//false=no unit; true=unit;
  82. };
  83.  
  84. MapLocation mlMap[MAPWIDTH][MAPHEIGHT];//map array
  85.  
  86. //rendering functionprototype
  87. void RenderFunc(LPDIRECTDRAWSURFACE7 lpddsDst,RECT* rcClip,int xDst,int yDst,int xMap,int yMap);
  88.  
  89. //////////////////////////////////////////////////////////////////////////////
  90. //WINDOWPROC
  91. //////////////////////////////////////////////////////////////////////////////
  92. LRESULT CALLBACK TheWindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
  93. {
  94.     //which message did we get?
  95.     switch(uMsg)
  96.     {
  97.     case WM_KEYDOWN:
  98.         {
  99.             switch(wParam)
  100.             {
  101.             case VK_ESCAPE:
  102.                 {
  103.                     DestroyWindow(hWndMain);
  104.                     return(0);
  105.                 }break;
  106.             case VK_NUMPAD1:
  107.                 {
  108.                     idMoveUnit=ISO_SOUTHWEST;
  109.                     bMoveUnit=true;
  110.                 }break;
  111.             case VK_NUMPAD2:
  112.                 {
  113.                     idMoveUnit=ISO_SOUTH;
  114.                     bMoveUnit=true;
  115.                 }break;
  116.             case VK_NUMPAD3:
  117.                 {
  118.                     idMoveUnit=ISO_SOUTHEAST;
  119.                     bMoveUnit=true;
  120.                 }break;
  121.             case VK_NUMPAD4:
  122.                 {
  123.                     idMoveUnit=ISO_WEST;
  124.                     bMoveUnit=true;
  125.                 }break;
  126.             case VK_NUMPAD6:
  127.                 {
  128.                     idMoveUnit=ISO_EAST;
  129.                     bMoveUnit=true;
  130.                 }break;
  131.             case VK_NUMPAD7:
  132.                 {
  133.                     idMoveUnit=ISO_NORTHWEST;
  134.                     bMoveUnit=true;
  135.                 }break;
  136.             case VK_NUMPAD8:
  137.                 {
  138.                     idMoveUnit=ISO_NORTH;
  139.                     bMoveUnit=true;
  140.                 }break;
  141.             case VK_NUMPAD9:
  142.                 {
  143.                     idMoveUnit=ISO_NORTHEAST;
  144.                     bMoveUnit=true;
  145.                 }break;
  146.             }
  147.         }break;
  148.     case WM_DESTROY://the window is being destroyed
  149.         {
  150.  
  151.             //tell the application we are quitting
  152.             PostQuitMessage(0);
  153.  
  154.             //handled message, so return 0
  155.             return(0);
  156.  
  157.         }break;
  158.     case WM_PAINT://the window needs repainting
  159.         {
  160.             //a variable needed for painting information
  161.             PAINTSTRUCT ps;
  162.             
  163.             //start painting
  164.             HDC hdc=BeginPaint(hwnd,&ps);
  165.  
  166.             /////////////////////////////
  167.             //painting code would go here
  168.             /////////////////////////////
  169.  
  170.             //end painting
  171.             EndPaint(hwnd,&ps);
  172.                         
  173.             //handled message, so return 0
  174.             return(0);
  175.         }break;
  176.     }
  177.  
  178.     //pass along any other message to default message handler
  179.     return(DefWindowProc(hwnd,uMsg,wParam,lParam));
  180. }
  181.  
  182.  
  183. //////////////////////////////////////////////////////////////////////////////
  184. //WINMAIN
  185. //////////////////////////////////////////////////////////////////////////////
  186. int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)
  187. {
  188.     //assign instance to global variable
  189.     hInstMain=hInstance;
  190.  
  191.     //create window class
  192.     WNDCLASSEX wcx;
  193.  
  194.     //set the size of the structure
  195.     wcx.cbSize=sizeof(WNDCLASSEX);
  196.  
  197.     //class style
  198.     wcx.style=CS_OWNDC | CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
  199.  
  200.     //window procedure
  201.     wcx.lpfnWndProc=TheWindowProc;
  202.  
  203.     //class extra
  204.     wcx.cbClsExtra=0;
  205.  
  206.     //window extra
  207.     wcx.cbWndExtra=0;
  208.  
  209.     //application handle
  210.     wcx.hInstance=hInstMain;
  211.  
  212.     //icon
  213.     wcx.hIcon=LoadIcon(NULL,IDI_APPLICATION);
  214.  
  215.     //cursor
  216.     wcx.hCursor=LoadCursor(NULL,IDC_ARROW);
  217.  
  218.     //background color
  219.     wcx.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH);
  220.  
  221.     //menu
  222.     wcx.lpszMenuName=NULL;
  223.  
  224.     //class name
  225.     wcx.lpszClassName=WINDOWCLASS;
  226.  
  227.     //small icon
  228.     wcx.hIconSm=NULL;
  229.  
  230.     //register the window class, return 0 if not successful
  231.     if(!RegisterClassEx(&wcx)) return(0);
  232.  
  233.     //create main window
  234.     hWndMain=CreateWindowEx(0,WINDOWCLASS,WINDOWTITLE, WS_POPUP | WS_VISIBLE,0,0,320,240,NULL,NULL,hInstMain,NULL);
  235.  
  236.     //error check
  237.     if(!hWndMain) return(0);
  238.  
  239.     //if program initialization failed, then return with 0
  240.     if(!Prog_Init()) return(0);
  241.  
  242.     //message structure
  243.     MSG msg;
  244.  
  245.     //message pump
  246.     for(;;)    
  247.     {
  248.         //look for a message
  249.         if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
  250.         {
  251.             //there is a message
  252.  
  253.             //check that we arent quitting
  254.             if(msg.message==WM_QUIT) break;
  255.             
  256.             //translate message
  257.             TranslateMessage(&msg);
  258.  
  259.             //dispatch message
  260.             DispatchMessage(&msg);
  261.         }
  262.  
  263.         //run main game loop
  264.         Prog_Loop();
  265.     }
  266.     
  267.     //clean up program data
  268.     Prog_Done();
  269.  
  270.     //return the wparam from the WM_QUIT message
  271.     return(msg.wParam);
  272. }
  273.  
  274. //////////////////////////////////////////////////////////////////////////////
  275. //INITIALIZATION
  276. //////////////////////////////////////////////////////////////////////////////
  277. bool Prog_Init()
  278. {
  279.     //create IDirectDraw object
  280.     lpdd=LPDD_Create(hWndMain,DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT);
  281.  
  282.     //set display mode
  283.     lpdd->SetDisplayMode(640,480,16,0,0);
  284.  
  285.     //create primary surface
  286.     lpddsMain=LPDDS_CreatePrimary(lpdd,1);
  287.  
  288.     //get back buffer
  289.     lpddsBack=LPDDS_GetSecondary(lpddsMain);
  290.  
  291.     //create the frame buffer
  292.     lpddsFrame=LPDDS_CreateOffscreen(lpdd,640,480);
  293.  
  294.     //load in the mousemap
  295.     MouseMap.Load("MouseMap.bmp");
  296.  
  297.     //set up the tile plotter
  298.     TilePlotter.SetMapType(ISOMAP_DIAMOND);//diamond mode
  299.     TilePlotter.SetTileSize(MouseMap.GetWidth(),MouseMap.GetHeight());//grab width and height from mousemap
  300.  
  301.     //set up tile walker to diamond mode
  302.     TileWalker.SetMapType(ISOMAP_DIAMOND);
  303.  
  304.     //set up screeen space
  305.     RECT rcTemp;
  306.     SetRect(&rcTemp,0,0,640,480);
  307.     Scroller.SetScreenSpace(&rcTemp);
  308.  
  309.     //load in tiles and cursor
  310.     tsBack.Load(lpdd,"backgroundts.bmp");
  311.     tsTree.Load(lpdd,"treets.bmp");
  312.     tsUnit.Load(lpdd,"unit_warrior.bmp");
  313.  
  314.     //grab tile extent from tileset
  315.     CopyRect(&rcTemp,&tsBack.GetTileList()[0].rcDstExt);
  316.  
  317.     //calculate the worldspace
  318.     Scroller.CalcWorldSpace(&TilePlotter,&rcTemp,MAPWIDTH,MAPHEIGHT);
  319.  
  320.     //calculate the mousemap reference point
  321.     MouseMap.CalcReferencePoint(&TilePlotter,&rcTemp);
  322.  
  323.     //calculate anchor space
  324.     Scroller.CalcAnchorSpace();
  325.  
  326.     //set wrap modes for scroller
  327.     Scroller.SetHWrapMode(WRAPMODE_CLIP);
  328.     Scroller.SetVWrapMode(WRAPMODE_CLIP);
  329.  
  330.     //set scroller anchor to (0,0)
  331.     Scroller.GetAnchor()->x=0;
  332.     Scroller.GetAnchor()->y=0;
  333.  
  334.     //attach scrolelr and tilewalker to mousemap
  335.     MouseMap.SetScroller(&Scroller);
  336.     MouseMap.SetTileWalker(&TileWalker);
  337.  
  338.     //set up the map to a random tilefield
  339.     for(int x=0;x<MAPWIDTH;x++)
  340.     {
  341.         for(int y=0;y<MAPHEIGHT;y++)
  342.         {
  343.             mlMap[x][y].bTree=((rand()%2)==1);//random tree
  344.             mlMap[x][y].bUnit=false;//no unit
  345.         }
  346.     }
  347.  
  348.     //calculate the extent rect
  349.     RECT rcExtent;
  350.     CopyRect(&rcExtent,&tsBack.GetTileList()[0].rcDstExt);//set to background extent
  351.     UnionRect(&rcExtent,&rcExtent,&tsTree.GetTileList()[0].rcDstExt);//union with tree extent
  352.     UnionRect(&rcExtent,&rcExtent,&tsUnit.GetTileList()[0].rcDstExt);//union with unit extent
  353.  
  354.     //set up the renderer
  355.     Renderer.SetBackBuffer(lpddsBack);
  356.     Renderer.SetExtentRect(&rcExtent);
  357.     Renderer.SetFrameBuffer(lpddsFrame);
  358.     Renderer.SetMapSize(MAPWIDTH,MAPHEIGHT);
  359.     Renderer.SetMouseMap(&MouseMap);
  360.     Renderer.SetPlotter(&TilePlotter);
  361.     Renderer.SetRenderFunction(RenderFunc);
  362.     Renderer.SetScroller(&Scroller);
  363.     Renderer.SetUpdateRectCount(100);
  364.     Renderer.SetWalker(&TileWalker);
  365.  
  366.     //set the position of the unit
  367.     ptUnit.x=rand()%MAPWIDTH;
  368.     ptUnit.y=rand()%MAPHEIGHT;
  369.     ptUnitOld=ptUnit;//set the old position to the same position
  370.     mlMap[ptUnit.x][ptUnit.y].bUnit=true;//set the unit on the map
  371.     bMoveUnit=false;//set unit movement to false
  372.  
  373.     //plot the position of the unit
  374.     POINT ptPos=TilePlotter.PlotTile(ptUnit);
  375.  
  376.     ptPos.x-=(Scroller.GetScreenSpaceWidth()/2);//center the unit horizontally
  377.     ptPos.y-=(Scroller.GetScreenSpaceHeight()/2);//center the unit vertically
  378.  
  379.     //set the anchor
  380.     Scroller.SetAnchor(&ptPos);
  381.     Scroller.WrapAnchor();
  382.  
  383.     //update the entire screenspace
  384.     Renderer.AddRect(Scroller.GetScreenSpace());
  385.  
  386.     return(true);//return success
  387. }
  388.  
  389. //////////////////////////////////////////////////////////////////////////////
  390. //CLEANUP
  391. //////////////////////////////////////////////////////////////////////////////
  392. void Prog_Done()
  393. {
  394.     //release frame buffer
  395.     LPDDS_Release(&lpddsFrame);
  396.  
  397.     //release main/back surfaces
  398.     LPDDS_Release(&lpddsMain);
  399.  
  400.     //release directdraw
  401.     LPDD_Release(&lpdd);
  402. }
  403.  
  404. //////////////////////////////////////////////////////////////////////////////
  405. //MAIN GAME LOOP
  406. //////////////////////////////////////////////////////////////////////////////
  407. void Prog_Loop()
  408. {
  409.     //set scroll to 0,0
  410.     ptScroll.x=0;
  411.     ptScroll.y=0;
  412.  
  413.     //if we are to move the unit
  414.     if(bMoveUnit)
  415.     {
  416.         //calculate the next position of the unit
  417.         POINT ptNextPos=TileWalker.TileWalk(ptUnit,idMoveUnit);
  418.  
  419.         //bounds checking
  420.         if(ptNextPos.x<0) bMoveUnit=false;
  421.         if(ptNextPos.y<0) bMoveUnit=false;
  422.         if(ptNextPos.x>=MAPWIDTH) bMoveUnit=false;
  423.         if(ptNextPos.y>=MAPHEIGHT) bMoveUnit=false;
  424.         
  425.         //are we still moving the unit?
  426.         if(bMoveUnit)
  427.         {
  428.             //set the unit position to ptnextpos
  429.             ptUnit=ptNextPos;
  430.  
  431.             //plot the units next position
  432.             POINT ptPlot=TilePlotter.PlotTile(ptUnit);
  433.  
  434.             //translate plot position into screen coordinates
  435.             ptPlot=Scroller.WorldToScreen(ptPlot);
  436.  
  437.             //check for scrolling
  438.             if(ptPlot.x<0) ptScroll.x=-320;
  439.             if(ptPlot.y<0) ptScroll.y=-240;
  440.             if(ptPlot.x>640) ptScroll.x=320;
  441.             if(ptPlot.y>480) ptScroll.y=240;
  442.         }
  443.     }
  444.  
  445.     //scroll the map
  446.     Renderer.ScrollFrame(ptScroll.x,ptScroll.y);
  447.  
  448.     //if we are still moving the unit
  449.     if(bMoveUnit)
  450.     {
  451.         //reset the old position
  452.         mlMap[ptUnitOld.x][ptUnitOld.y].bUnit=false;
  453.         
  454.         //set the new position
  455.         mlMap[ptUnit.x][ptUnit.y].bUnit=true;
  456.  
  457.         //add update tiles to renderer
  458.         Renderer.AddTile(ptUnitOld.x,ptUnitOld.y);
  459.         Renderer.AddTile(ptUnit.x,ptUnit.y);
  460.  
  461.         //set moveunit to false
  462.         bMoveUnit=false;
  463.  
  464.         //set old position to current position
  465.         ptUnitOld=ptUnit;
  466.     }
  467.  
  468.     //update the frame
  469.     Renderer.UpdateFrame();
  470.  
  471.     //flip to show the back buffer
  472.     lpddsMain->Flip(0,DDFLIP_WAIT);
  473. }
  474.  
  475. void RenderFunc(LPDIRECTDRAWSURFACE7 lpddsDst,RECT* rcClip,int xDst,int yDst,int xMap,int yMap)
  476. {
  477.     //put background tile
  478.     tsBack.ClipTile(lpddsDst,rcClip,xDst,yDst,0);
  479.     //check for a tree
  480.     if(mlMap[xMap][yMap].bTree)
  481.     {
  482.         //put tree
  483.         tsTree.ClipTile(lpddsDst,rcClip,xDst,yDst,0);
  484.     }
  485.     //check for the unit
  486.     if(mlMap[xMap][yMap].bUnit)
  487.     {
  488.         //put unit
  489.         tsUnit.ClipTile(lpddsDst,rcClip,xDst,yDst,0);
  490.     }
  491. }
  492.